import Cesium, { ScreenSpaceEventHandler } from '../Ces/Cesium'
import Overlay from '../Widgets/Overlay';

function setScale(obj, value) {
  if (!Cesium.defined(obj) || (!value && !Cesium.defined(obj.originalScale))) {
    return;
  }
  if (!Cesium.defined(obj.originalScale)) {
    obj.originalScale = Cesium.defined(obj.scale) ? obj.scale : 1.0;
  }

  obj.scale = value ? obj.originalScale * CommonPickHandler.highLightScale : obj.originalScale;
  if (obj instanceof Cesium.LabelGraphics) {
    if (Cesium.defined(obj.pixelOffset) && !Cesium.defined(obj.originalOffset)) {
      obj.originalOffset = obj.pixelOffset.getValue();
      obj.highLightOffset = Cesium.Cartesian2.clone(obj.originalOffset);
      obj.highLightOffset.x *= CommonPickHandler.highLightScale;
    }
    obj.pixelOffset.setValue(value ? obj.highLightOffset : obj.originalOffset);
  }
}

function setColor(obj, value) {
  if (!Cesium.defined(obj) || (!value && !Cesium.defined(obj.originalColor))) {
    return;
  }
  if (!Cesium.defined(obj.originalColor)) {
    obj.originalColor = Cesium.defined(obj.color) ? obj.color : Cesium.Color.WHITE;

    obj.hightLightColor = Cesium.Color.clone(CommonPickHandler.highLightColor);
    if (Cesium.Color.equals(obj.originalColor, obj.hightLightColor)) {
      Cesium.Color.divideByScalar(obj.hightLightColor, 2.0, obj.hightLightColor);
      obj.hightLightColor.a = 1.0;
    }
  }
  obj.color = value ? obj.hightLightColor : obj.originalColor;
}

function setMaterial(obj, value) {
  if (!Cesium.defined(obj) || !Cesium.defined(obj.material) || (!value && !Cesium.defined(obj.originalMaterial))) {
    return;
  }

  if (!Cesium.defined(obj.originalMaterial)) {
    obj.originalMaterial = obj.material;

    const color = Cesium.Color.clone(CommonPickHandler.highLightColor);

    if (Cesium.Color.equals(obj.material.color._value, color)) {
      Cesium.Color.divideByScalar(color, 2.0, color);
      color.a = 1.0;
    }
    obj.hightLightMaterial = new Cesium.ColorMaterialProperty(color);
  }

  obj.material = value ? obj.hightLightMaterial : obj.originalMaterial;
}


class CommonPickHandler {
  static highLightColor
  static highLightScale = 1.5;
  static highLightMaterial

  currentHighLight
  _scene
  _handlerMove: ScreenSpaceEventHandler
  _handlerDown: ScreenSpaceEventHandler
  _featurePickEvent = new Cesium.Event()
  _removeEventSubscription

  onMovePickFeature
  _tooltip
  constructor(viewer, options) {
    this._scene = viewer.scene;

    if (!Cesium.defined(CommonPickHandler.highLightColor)) {
      CommonPickHandler.highLightColor = Cesium.Color.RED;
    }
    this._removeEventSubscription = this._featurePickEvent.addEventListener(
      this._onPickFeature,
      this,
    );

    if (options.infomation??true) {
      this.onMovePickFeature = this.onPickFeature;
    } else {
      this.onPickFeature = undefined;
      this.onMovePickFeature = undefined;
    }

    this._tooltip = new Overlay(viewer);
    this._tooltip.createGraph(viewer.container);
  }

  get featurePickEvent() {
    return this._featurePickEvent;
  }

  onPickFeature(
    entity,
    propertyName1,
    screenPosition,
    oldValue,
  ) {
    if (Cesium.defined(entity)) {
      let pickInfo = '';

      if (entity instanceof Cesium.Cesium3DTileFeature) {
        const propertyNames = entity.getPropertyNames();
        const length = propertyNames.length;

        for (let i = 0; i < length; ++i) {
          const propertyName = propertyNames[i];
          const message = propertyName + ': ' + entity.getProperty(propertyName);

          pickInfo += message + '<br/>';
        }
      } else if (entity.id instanceof Cesium.Entity) {
        if (Cesium.defined(entity.id.kml) && Cesium.defined(entity.id.kml.extendedData)) {
          for (const data in entity.id.kml.extendedData) {
            const message = data + ': ' + entity.id.kml.extendedData[data].value;

            pickInfo += message + '<br/>';
          }
        } else if (Cesium.defined(entity.id.properties)) {
          const length = entity.id.properties.propertyNames.length;

          for (let i = 0; i < length; ++i) {
            const propertyName = entity.id.properties.propertyNames[i];
            const message = propertyName + ': ' + entity.id.properties[propertyName];

            pickInfo += message + '<br/>';
          }
        }
      }
      this._tooltip.showAt(screenPosition, pickInfo);
    } else {
      this._tooltip.setVisible(false);
    }
  }

  _onPickFeature(
    entity,
    propertyName,
    newValue,
    oldValue,
  ) {
    if (propertyName === 'onPickFeature') {
      this.onPickFeature(entity, propertyName, newValue, oldValue)
    } else if (propertyName === 'onMovePickFeature') {
      this.onPickFeature(entity, propertyName, newValue, oldValue)
    }
  }

  static isAllowPicking(pickFeature) {
    if (!pickFeature) return true
    let allowPicking = true;

    if (Cesium.defined(pickFeature.id)) {
      if (Cesium.defined(pickFeature.id.allowPicking)) {
        allowPicking = pickFeature.id.allowPicking
      }
      else if (Cesium.defined(pickFeature.id.entityCollection) &&
        Cesium.defined(pickFeature.id.entityCollection.owner) &&
        Cesium.defined(pickFeature.id.entityCollection.owner.allowPicking)
      ) {
        allowPicking = pickFeature.id.entityCollection.owner.allowPicking;
      }
    }
    else if (Cesium.defined(pickFeature.collection)
      && Cesium.defined(pickFeature.collection.allowPicking)
    ) {
      allowPicking = pickFeature.collection.allowPicking;
    }

    return allowPicking;
  }

  static isAllowHighLight(pickFeature) {
    if (!pickFeature) return false
    let allowHighLight = true;

    if (Cesium.defined(pickFeature.id)) {
      if (Cesium.defined(pickFeature.id.allowHighLight)) {
        allowHighLight = pickFeature.id.allowHighLight
      }
      else if (Cesium.defined(pickFeature.id.entityCollection) &&
        Cesium.defined(pickFeature.id.entityCollection.owner) &&
        Cesium.defined(pickFeature.id.entityCollection.owner.allowHighLight)
      ) {
        allowHighLight = pickFeature.id.entityCollection.owner.allowHighLight;
      }
    }
    else if (Cesium.defined(pickFeature.collection)
      && Cesium.defined(pickFeature.collection.allowHighLight)
    ) {
      allowHighLight = pickFeature.collection.allowHighLight;
    }

    return allowHighLight;
  }

  clearHighlight() {
    if (Cesium.defined(this.currentHighLight)) {
      if (Cesium.defined(this.currentHighLight.id)) {
        const {
          model, point, billboard, label
          , polygon, polyline,
        } = this.currentHighLight.id;

        setColor(model, false);

        setScale(billboard, false);
        setScale(label, false);

        setMaterial(point, false);
        setMaterial(polygon, false);
        setMaterial(polyline, false);
      }

      setColor(this.currentHighLight, false);
      if (this.currentHighLight.primitive instanceof Cesium.Billboard) {
        setScale(this.currentHighLight.primitive, false);
      }
      this.currentHighLight = undefined;
    }
  }

  start() {
    const that = this;

    this._handlerMove = new Cesium.ScreenSpaceEventHandler(this._scene.canvas);
    this._handlerMove.setInputAction((movement) => {
      const pickedFeature = that._scene.pick(movement.endPosition);

      let pickChanged = Cesium.defined(this.currentHighLight) && !Cesium.defined(pickedFeature);

      if (pickedFeature !== this.currentHighLight) {
        that.clearHighlight();
        pickChanged = true;
        this.currentHighLight = pickedFeature;
        const allowPicking = CommonPickHandler.isAllowPicking(pickedFeature);
        if (!allowPicking) {
          this.currentHighLight = undefined;
          return;
        }

        const allowHighLight = CommonPickHandler.isAllowHighLight(pickedFeature)
        if (allowHighLight) {
          if (Cesium.defined(pickedFeature.id)) {
            const {
              model, point, billboard, label
              , polygon, polyline,
            } = pickedFeature.id;

            if (allowPicking) {
              setMaterial(point, true);
              setMaterial(polygon, true);
              setMaterial(polyline, true);
            }

            setColor(model, true);
            setScale(billboard, true);
            setScale(label, true);
          }
          setColor(pickedFeature, true);

          if (pickedFeature.primitive instanceof Cesium.Billboard) {
            setScale(pickedFeature.primitive, true);
          }
        }
      }

      if (Cesium.defined(that.onMovePickFeature) && pickChanged) {
        that.featurePickEvent.raiseEvent(pickedFeature, 'onMovePickFeature', movement.endPosition, '');
      }
    }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);


    // on mouse down
    this._handlerDown = new Cesium.ScreenSpaceEventHandler(this._scene.canvas);
    this._handlerDown.setInputAction((movement) => {
      if (Cesium.defined(that.onPickFeature)) {
        const pickedFeature = that._scene.pick(movement.position);
        const allowPicking = CommonPickHandler.isAllowPicking(pickedFeature);

        if (allowPicking) {
          that.featurePickEvent.raiseEvent(pickedFeature, 'onPickFeature', movement.position, '');
        }
      }
    }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
  }

  destroy() {
    //@ts-ignore
    this._handlerMove = this._handlerMove && this._handlerMove.destroy()
    //@ts-ignore
    this._handlerDown = this._handlerDown && this._handlerDown.destroy()
    this._tooltip = this._tooltip && this._tooltip.destroy()
    if (this._removeEventSubscription) this._removeEventSubscription()
  }

  isDestroyed() {
    return false
  }

}




export default CommonPickHandler;
